import { join } from 'path'

import { App, Configuration, Config } from '@midwayjs/decorator'
import { ILifeCycle } from '@midwayjs/core'
import { Application } from 'egg'

import * as orm from '@midwayjs/orm'
import * as axios from '@midwayjs/axios'
import * as cache from '@midwayjs/cache'
import * as task from '@midwayjs/task'

import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'
import { createPrivateKey, createPublicKey, KeyObject } from 'crypto'
import { generateKeyPair } from 'jose/util/generate_key_pair'

@Configuration({
  importConfigs: [join(__dirname, './config')],
  conflictCheck: true,
  imports: [
    orm,
    axios,
    cache,
    task
  ]
})
export class ContainerLifeCycle implements ILifeCycle {

  @App()
  app: Application

  @Config('jwt')
  jwtConfig: any

  async onReady() {

    // Loaded RSA private key
    const { keyPath } = this.jwtConfig

    if (keyPath) {
      const mixinConfig: {
        publicKey?: KeyObject,
        privateKey?: KeyObject
      } = {}

      try {
        const pem = readFileSync(keyPath)

        mixinConfig.publicKey = createPublicKey(pem)
        mixinConfig.privateKey = createPrivateKey(pem)
      } catch (err) {
        const {
          publicKey,
          privateKey
        } = await generateKeyPair('RS256')

        mixinConfig.publicKey = publicKey as KeyObject
        mixinConfig.privateKey = privateKey as KeyObject

        const keyDir = keyPath
          .split('/')
          .slice(0, -1)
          .join('/')

        if (!existsSync(keyDir)){
          mkdirSync(keyDir, { recursive: true })
        }

        const keyBuffer = mixinConfig.privateKey
          .export({
            type: 'pkcs8',
            format: 'pem'
          })

        writeFileSync(keyPath, keyBuffer)
      }

      this.jwtConfig.raw = mixinConfig
    }
  }
}
